/**
 * @author Alterado por Carolina Y. Ji
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
/* ****************************************************************** */
/* @autores Daniel M.L. Vizeu - Pablo de Barros Fernandes             */
/*                                                                    */
/* Univercidade - Ci�ncia da Computa��o - Projeto de Final de curso   */
/* SISTEMA DE INFER�NCIA NEBULOSO ON LINE                             */
/* Orientador: Orlando Bernardo Filho                                 */
/*                                                                    */
/* ****************************************************************** */

package fuzzy;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList; 
import java.util.Iterator;

public class DeFuzzy{
    public Connection con = null;
    private String 	connectionUrl="jdbc:postgresql://localhost:5432/PF2";	
    private Statement stmt = null;     
    private int Cod_regra;
    		int Cod_sistema;
    		int Cod_variavel1;
    		double Valor_var1;
    		int Cod_termo1;
    		double Alfa1;
    		int Cod_variavel2;
    		double Valor_var2;
    		int Cod_termo2;
    		double Alfa2;
    		int Cod_variavel3;
    		int Valor_var3;
    		int Cod_termo3;
    		double Alfa3;
    		double Menor_alfa;
            int Cod_Termo_Cons;
            double denominadorRegra = 0;
            double numeradorRegra = 0;
            double ValorFinal = 0;
            ArrayList regras = new ArrayList();
            ArrayList novoAlfa = new ArrayList();
                            
    public DeFuzzy(int cod_sistema, int cod_variavel1, double valor_var1, int cod_variavel2, double valor_var2, int cod_variavel3, int valor_var3) {
        Cod_sistema = cod_sistema;
        Cod_variavel1 = cod_variavel1;
        Valor_var1 = valor_var1;
        Cod_variavel2 = cod_variavel2;
        Valor_var2 = valor_var2;
        Cod_variavel3 = cod_variavel3;
        Valor_var3 = valor_var3;
    }
        
    public double calculaAlfa (double coef_linear, double coef_angular, double valor_var) {
        double alfa = (coef_angular * valor_var) + coef_linear;
		return alfa;
    }
    
    public void ConnectionBean(){
		
		try{
			Class.forName("org.postgresql.Driver");
			con = DriverManager.getConnection(connectionUrl,"postgres","post");
			stmt = con.createStatement();
		}
		catch(Exception e){
			System.out.println(e.getMessage());
			con = null;
		}	
	}

    public int verificarTermoRegra(int cod_regra, int cod_variavel){
        int cod_termo = 0;
        String sql = "SELECT termo.cod_termo FROM termo, regra, antecedente " + 
        			 "WHERE ( termo.cod_termo 	 = antecedente.cod_termo OR termo.cod_termo = regra.cod_termo_cons) AND "+
        			 		" regra.cod_regra  	 = antecedente.cod_regra AND "+ 
        			 		" regra.cod_sistema  = "+ Cod_sistema +" AND "+ 
        			 		" regra.cod_regra    = "+ cod_regra +" AND "+ 
        			 		" termo.cod_variavel_linguistica = "+ cod_variavel +" ";

        try{
            
            ConnectionBean ();
 			if(con == null){
 				System.out.println("Servidor ocupado.Tente mais tarde!");
 			}
 			ResultSet rs = stmt.executeQuery(sql);
 			if (rs.next()){
 			    cod_termo = rs.getInt("cod_termo");
 			}
 			con.close();
	        stmt.close();
 			return cod_termo;
 		}
 		catch (SQLException e) {
 			e.printStackTrace();
 			System.out.println(e);
 			return -1;
 		}
 		catch (Exception e) {
 			e.printStackTrace();
 			System.out.println(e);
 			return -1;
 		}
    }
    
    public double avaliarMi (int cod_termo, double valor_var){
        int CodSegmentos_termo;
        double alfa = 0;
        String sql = "SELECT cod_segmento, coef_angular, coef_linear FROM segmento WHERE cod_termo = "+ cod_termo +" AND (intervalo_esquerdo <= "+ valor_var +") AND (intervalo_direito  >= "+ valor_var + ") AND (mi_esquerdo <> 0 OR mi_direito <> 0 ) " ;
        
        try{
           
            ConnectionBean ();
 			if(con == null){
 				System.out.println("Servidor ocupado.Tente mais tarde!");
 			}
 			ResultSet rs = stmt.executeQuery(sql);
			if(rs.next()){
					CodSegmentos_termo = rs.getInt("cod_segmento");
					double coef_linear = rs.getDouble("coef_linear");
					double coef_angular = rs.getDouble("coef_angular");
					alfa = calculaAlfa(coef_linear, coef_angular, valor_var);
					return alfa;
			}
			con.close();
	        stmt.close();
 			return alfa;
        }
 		catch (SQLException e) {
 			System.out.println(e);
 			return -1;
 		}
 		catch (Exception e) {
 			System.out.println(e);
 			return -1;
 		}
    }

    public int verificarTermoConsRegra(int cod_sistema, int cod_regra){
        int cod_termo = 0;
        String sql = "SELECT cod_termo_cons FROM regra " + 
        			 "WHERE   regra.cod_sistema  = "+ Cod_sistema +" AND "+ 
        			 		" regra.cod_regra    = "+ cod_regra +" ";

        try{
            
            ConnectionBean ();
 			if(con == null){
 				System.out.println("Servidor ocupado.Tente mais tarde!");
 			}
 			ResultSet rs = stmt.executeQuery(sql);
 			if (rs.next()){
 			   cod_termo = rs.getInt("cod_termo_cons");
 			}
 			con.close();
	        stmt.close();
 			return cod_termo;
 		}
 		catch (SQLException e) {
 			System.out.println(e);
 			return -1;
 		}
 		catch (Exception e) {
 			System.out.println(e);
 			return -1;
 		}
    }    
    
    public double calculaCentroide(double intEsq, double intDir, double coefAng, double coefLinear) {
        double centroide;
        double potencia1 = Math.pow(intDir, 3);
        double potencia2 = Math.pow(intDir, 2);
        double potencia3 = Math.pow(intEsq, 3);
        double potencia4 = Math.pow(intEsq, 2);
        double aux1 = (potencia1 * coefAng) / 3;
        double aux2 = (potencia2 * coefLinear) / 2;
        double aux3 = (potencia3 * coefAng) / 3;
        double aux4 = (potencia4 * coefLinear) / 2;
        
        centroide = (aux1 + aux2 - aux3 - aux4);
        return centroide;
    }

    
    
    public double calculaArea(double intEsq, double intDir, double coefAng, double coefLinear) {
        double area;
        double potencia1 = Math.pow(intDir, 2);
        double potencia3 = Math.pow(intEsq, 2);
        double aux1 = (potencia1 * coefAng) / 2;
        double aux2 = (intDir * coefLinear);
        double aux3 = (potencia3 * coefAng) / 2;
        double aux4 = (intEsq * coefLinear);
        
        area = (aux1 + aux2 - aux3 - aux4);
        return area;
    }
  
    public double gravaTabelaTemp(int codTermoCons) {
        double coefAng;
	    double coefLinear;
	    double numeradorSegmento;
	    double denominadorSegmento;
	    double CentroideRegra = 0;
	    int retInsere = 0;
	    numeradorRegra = 0;
	    denominadorRegra = 0;

	    String sql = "SELECT cod_segmento, intervalo_esquerdo, intervalo_direito, mi_esquerdo, mi_direito FROM segmento WHERE cod_termo = "+ codTermoCons +" AND (mi_esquerdo <> 0 OR mi_direito <> 0 ) ";
        
        try{
            
            ConnectionBean ();
			if(con == null){
				System.out.println("Servidor ocupado.Tente mais tarde!");
				return -1;
			}
			ResultSet rs = stmt.executeQuery(sql);
			while(rs.next()){
			    int     codSegmento = rs.getInt("cod_segmento");
			    double  intEsq = rs.getDouble("intervalo_esquerdo");
			    double  intDir = rs.getDouble("intervalo_direito");
			    double  miEsq = rs.getDouble("mi_esquerdo");
			    double  miDir = rs.getDouble("mi_direito");
			    numeradorSegmento = 0;
			    denominadorSegmento = 0;
		  
			    if (miEsq == 1) {
			        miEsq = Menor_alfa;
			    }
			    if (miDir == 1) {
			        miDir = Menor_alfa;
			    }
			    coefAng 	= CalculaCoeficientes.Angular ( miEsq, miDir, intEsq, intDir);
		    	coefLinear  = CalculaCoeficientes.Linear  ( miEsq, miDir, intEsq, intDir);
		    	//retInsere   = insereTabelaTemp(codTermoCons, codSegmento, intEsq, intDir, coefAng, coefLinear, miEsq, miDir);
		    	//if (retInsere <= 0){
		    	//    return retInsere;
		    	//}
		    	
		    	numeradorSegmento 	= calculaCentroide (intEsq, intDir, coefAng, coefLinear);
		    	denominadorSegmento	= calculaArea (intEsq, intDir, coefAng, coefLinear);
		    	
		    	numeradorRegra		= numeradorRegra + (numeradorSegmento);
		    	denominadorRegra	= denominadorRegra + (denominadorSegmento);

			}
			CentroideRegra = numeradorRegra / denominadorRegra;
			con.close();
	        stmt.close();
			return CentroideRegra;
		}
		catch (SQLException e) {
			System.out.println(e.getMessage());
			return -1;
		}
		catch (Exception e) {
			System.out.println(e.getMessage());
			return -1;
		}
    }
 
    public double percorrerRegras(){
        double NumeradorGeral = 0;
        double DenominadorGeral = 0;
        double centroideRegra = 0;
        
        String sql = "SELECT cod_sistema, cod_regra, cod_termo_cons FROM regra WHERE cod_sistema = " + Cod_sistema + " "; 
        
        try{
           
            ConnectionBean ();
 			if(con == null){
 				System.out.println("Servidor ocupado.Tente mais tarde!");
 				return -1;
 			}
 			ResultSet rs = stmt.executeQuery(sql);
 			
 			while(rs.next()){
 			    centroideRegra = 0;
 			    denominadorRegra = 0;
 			    
 			    Cod_regra = rs.getInt("cod_regra"); //System.out.println(Cod_regra);
 			    System.out.println("Cod_regra "+Cod_regra);
 			    Cod_termo1 = verificarTermoRegra ( Cod_regra, Cod_variavel1 );
 			    if (Cod_termo1 > 0) { 
 			        Alfa1 = avaliarMi(Cod_termo1, Valor_var1);	
 			        System.out.println("Distancia valor var 1 "+Valor_var1);
 	 			    if (Alfa1 < 0) { 
 	 			        System.out.println("ERRO DO ALFA 1");
 	 			        return -1;
 				    }
			    }
			    else{
			        System.out.println("ERRO DO TERMO 1");
			        return -1;
			    }
			    
 			    Cod_termo2 = verificarTermoRegra ( Cod_regra, Cod_variavel2 );
 			    if (Cod_termo2 > 0) { 
 			        Alfa2 = avaliarMi(Cod_termo2, Valor_var2);			        
 	 			    if (Alfa2 < 0) { 
 	 			        System.out.println("ERRO DO ALFA 2");
 	 			        return -1;
 				    }
			    }
			    else{
			        System.out.println("ERRO DO TERMO 2");
			        return -1;
			    }

			    Cod_termo3 = verificarTermoRegra ( Cod_regra, Cod_variavel3 );
 			    if (Cod_termo3 > 0) { 
 			        Alfa3 = avaliarMi(Cod_termo3, Valor_var3);			        
 	 			    if (Alfa3 < 0) { 
 	 			        System.out.println("ERRO DO ALFA 3");
 	 			        return -1;
 				    }
			    }
			    else{
			        System.out.println("ERRO DO TERMO 3");
			        return -1;
			    }
 			    if (Alfa1 <= Alfa2){
 			        Menor_alfa = Alfa1; 
 			    }
 			    else{
 			        Menor_alfa = Alfa2;
 			    }
 			    if (Alfa3 <= Menor_alfa)
				Menor_alfa = Alfa3;
 			    if (Menor_alfa > 0){
 			       
 			       
 			       Cod_Termo_Cons = verificarTermoConsRegra(Cod_sistema, Cod_regra );
 			       centroideRegra = gravaTabelaTemp(Cod_Termo_Cons);
 			       regras.add(new Integer(Cod_regra));
 			       novoAlfa.add(new Double(Menor_alfa));
 			       
 			       //if (retgrava <= 0 ){
 			       //   System.out.println("ERRO AO INSERIR NA TABELA TEMPOR�RIA");
 			       //   return -1;
 			       //}
 			       
 			      NumeradorGeral   = NumeradorGeral + (centroideRegra * denominadorRegra);
 			      DenominadorGeral = DenominadorGeral + denominadorRegra;
			    }
 			}
 			ValorFinal = NumeradorGeral / DenominadorGeral;
 			con.close();
	        stmt.close();
 			return ValorFinal;
 		}
 		catch (SQLException e) {
 			System.out.println(e);
 			return -1;
 		}
 		catch (Exception e) {
 			System.out.println(e);
 			return -1;
 		}
    }
    public Iterator getRegras() {
	    Iterator Regras = regras.iterator();
        return Regras;
    }
    public Iterator getNovoAlfa() {
        Iterator Alfas = novoAlfa.iterator();
        return Alfas;
    }
}         
